﻿using System;
using System.Collections.Generic;
using SCG.SolarVengeanceEngine;
using SCG.General;

namespace SCG.SolarVengeance.Scenarios
{
    public class HelixNebula : Scenario
    {
        public override string Author
        {
            get
            {
                return "Ugly Green Things";
            }
        }

        //Describe the scene
        public override string Description
        {
            get
            {
                return "The Helix Nebula was one of the most brutal battles among the Star Lords.  Several large fleets converged on the " +
                    "resource-rich systems within the nebula to harness them for their own destructive ends.  The fleets fought to the bitter " +
                    "end for control of this nebula, and in the end, only one emerged victorious (with victory being a relative term).  " +
                    "WARNING:  The nebula is destructive, any starships within the nebula will be degraded over time.  " +
                    "The victory condition is Conquest-Deathmatch: Hold all starsystems within the nebula for 100 impulses.";
            }
        }

        //don't assign capitals
        public override bool AssignCapitals
        {
            get
            {
                return false;
            }
        }

        public override bool UsesCapitals
        {
            get
            {
                return false;
            }
        }

        public override int MaxPlayers
        {
            get
            {
                return 8;
            }
        }

        private ScenarioParameter enbNeb;

        public HelixNebula()
        {
            enbNeb = CreateParameter("Desctuctive Nebula Enabled?", 1, 0, 1);
        }

        //Dictionary for Victory Condition
        private int _counter = 0;
        private int _countdown = 100;
        private Player _lastOwner = null;

        //Build the scenario
        public override void BuildScenario(int numPlayers, int capitalValues, int startingResources)
        {

            //Create Star Cluster
            CreateStarCluster(10, 50, 50, 50, 50, 20, 5);
            for (int d = 1; d < Game.StarSystems.Count; d++)
            {
                StarSystem ss = Game.StarSystems[d];
                ss.Resources = Random(20, 500);
                ss.Value = Random(10, 30);
            }

            //Create the nebula
            CreateTerrainImage(TerrainType.Nebula, "HelixNebula", Random(35, 35), Random(35, 45), 0.7);

            //Determine fleet values for each player, they all share equal strengths
            int commandRange = Random(8, 13);
            int scanRange = Random(9, 15);
            int bs = Random(30, 50);
            int stRange = Random(8, 13);
            int spyRange = Random(5, 9);

            //Assign fleet locations of each player, make sure they are not too close to each other, and outside nebula
            List<SCGPoint> pts = new List<SCGPoint>();
            foreach (Player p in Game.Players)
            {
                SCGPoint testPoint = new SCGPoint();
                bool pointOK = false;
                do
                {
                    //get a random point about 40 spaces away from center
                    testPoint.X = Random(0, 99);
                    testPoint.Y = Random(0, 99);
                    double dist = Distance(testPoint.X, testPoint.Y, 50, 50);
                    if (dist > 35 && dist < 45)
                    {
                        pointOK = true;

                        //must also be at least 20 away from all other players
                        foreach(SCGPoint ptTest in pts)
                            if (Distance(testPoint.X, testPoint.Y, ptTest.X, ptTest.Y) < 20)
                            {
                                pointOK = false;
                                break;
                            }
                    }
                }
                while (!pointOK);

                //this is the fleet location!
                pts.Add(testPoint);

                //center Battlestation at this location
                int x = (int)testPoint.X;
                int y = (int)testPoint.Y;
                CreateStarShip(x, y, p, StarShipType.BattleStation, 6, bs, false);

                //create scanship below it
                CreateStarShip(x, y + 1, p, StarShipType.ScanShip, 20, scanRange, false);

                //create Drones
                for (int d = 0; d < 8; d++)
                    CreateStarShip(x - 4 + d, y + 4, p, StarShipType.Drone, 12, 0, false);

                //create W3 scouts
                for (int scout = 0; scout < 8; scout++)
                    CreateStarShip(x - 4, y - 4 + scout, p, StarShipType.WarShip, 14, 3, false);

                //create W4 battery
                for (int w4 = 0; w4 < 6; w4++)
                    CreateStarShip(x - 3, y - 3 + w4, p, StarShipType.WarShip, 12, 4, false);

                //create W6 battery & Elites
                for (int w6 = 0; w6 < 2; w6++)
                {
                    CreateStarShip(x - 2, y - 1 - w6, p, StarShipType.WarShip, 10, 6, false);
                    CreateStarShip(x - 2, y + 1 + w6, p, StarShipType.Elite, 20, 5, false);
                }

                //create SpyShip
                CreateStarShip(x, y - 2, p, StarShipType.SpyShip, 15, spyRange, false);

                //create CommandShip
                CreateStarShip(x, y - 1, p, StarShipType.CommandShip, 20, commandRange, false);

                //create StarTillery
                for (int st = 0; st < 2; st++)
                    CreateStarShip(x + 2, y - st, p, StarShipType.StarTillery, 20, stRange, false);

                //create cloaked groups
                for (int c = 0; c < 4; c++)
                    CreateStarShip(x - 1 + c, y - 4, p, StarShipType.WarShip, 15, 7, true);
            }

            //Create Pulsars just outside nebula perimiter
            int pulsars = Random(numPlayers + 1, numPlayers + 4);
            while (pulsars > 0)
            {
                bool pulsarOK = false;
                SCGPoint ptPulsar = new SCGPoint();
                do
                {
                    ptPulsar = new SCGPoint(Random(0, 99), Random(0, 99));
                    double dist = Distance(ptPulsar.X, ptPulsar.Y, 50, 50);
                    pulsarOK = dist < 15 && dist > 5;
                }
                while (!pulsarOK);
                CreatePulsar((int)ptPulsar.X, (int)ptPulsar.Y);
                pulsars--;
            }

            //Create wormholes in center that lead out
            int wormholes = Random(numPlayers + 1, numPlayers + 4);
            while (wormholes > 0)
            {
                bool wormholeOK = false;
                SCGPoint ptWormhole = new SCGPoint();
                do
                {
                    ptWormhole = new SCGPoint(Random(0, 99), Random(0, 99));
                    double dist = Distance(ptWormhole.X, ptWormhole.Y, 50, 50);
                    wormholeOK = dist > 25 && dist < 35;
                }
                while (!wormholeOK);
                CreateWormhole(Random(40, 60), Random(40, 60), (int)ptWormhole.X, (int)ptWormhole.Y);
                wormholes--;
            }
        }

        //Destructive Nebula code
        public override void ProcessImpulse(int impulse)
        {
            if (impulse == 1 && enbNeb.Value == 1)
            {
                DynamicEvents.DisplayMessage("The Helix Nebula is destructive to all starship types.");
            }
            if (enbNeb.Value == 1)
            foreach (StarShip ship in Game.StarShips)
            {
                if (Game.GetTerrain(ship.X, ship.Y) == 'n' || Game.GetTerrain(ship.X, ship.Y) == 'n')
                {
                    if (Random(0, 100) > 97)
                    {
                        DynamicEvents.AdjustShipValues(ship, ship.Engines, ship.MaxEngines, ship.Value - 1, ship.MaxValue, true);
                    }
                    if (Random(0, 100) > 97 && ship.Engines > 2)
                    {
                        DynamicEvents.AdjustShipValues(ship, ship.Engines - 1, ship.MaxEngines, ship.Value, ship.MaxValue, true);
                    }

                }
            }
        }

        //Custom Deathmatch-Conquest victory conditions.

        public override bool VictoryReached()
        {
            //Same Player must hold all Stars for 100 impulses
            if (Game.StarSystems[0].Owner == Game.StarSystems[1].Owner && Game.StarSystems[1].Owner == Game.StarSystems[2].Owner &&
                Game.StarSystems[2].Owner == Game.StarSystems[3].Owner && Game.StarSystems[3].Owner == Game.StarSystems[4].Owner &&
                Game.StarSystems[4].Owner == Game.StarSystems[5].Owner && Game.StarSystems[5].Owner == Game.StarSystems[6].Owner &&
                Game.StarSystems[6].Owner == Game.StarSystems[7].Owner && Game.StarSystems[7].Owner == Game.StarSystems[8].Owner &&
                Game.StarSystems[8].Owner == Game.StarSystems[9].Owner && Game.StarSystems[9].Owner == Game.StarSystems[0].Owner &&
                Game.StarSystems[0].Owner != null)
            {
                Player owner = Game.StarSystems[0].Owner;
                if (owner == _lastOwner)
                {
                    _counter++;
                    _countdown--;
                    DynamicEvents.DisplayMessage( _lastOwner.ToString() + " has conquered the Nebula, time to victory: " + _countdown.ToString());
                    if (_counter >= 100)
                    {
                        _lastOwner.Victor = true;
                        return true;
                    }
                }
                else
                {
                    _lastOwner = owner;
                    _counter = 0;
                    _countdown = 100;
                }
            }
            else
                _lastOwner = null;
            return false;
        }
    }
}
